 /* 
 * File:   State.h
 * Author: josep
 *
 * Created on 5 / desembre / 2010, 05:25
 */

#include <map>
#include <list>
#include <string>

#ifndef STATE_H
#define	STATE_H

using namespace std;

template <class T>
struct Types{
public:
    typedef T* p_toT;
};

template <class T>
class State{
public:
    /**
     * Valores de salida que retornan las funciones de tipo callback que se
     * ejecutaran al producirse una cambio de estado. CONTINUE indicarà que
     * la notificación del cambio de estado se continurà propagando al resto de
     * funciones callback suscritas a los cambios de estado que se produzcan
     * durante una transición. STOP_IN_THIS_SUBSCRIPTION impedirá la propagación
     * para aquellas funciones callback suscritas en la misma suscripción. Existen
     * 2 posibles susucripciones para cada cambio de estado, la suscripción activada
     * en el momento de abandonar una estado (SUBSCRIPTION_OUT) y la suscripción
     * activada en el momento entrar en un estado (SUSCRIPTION_IN).
     * La opción STOP se usarua para cancelar cualquier propagación sea de la
     * suscripción que sea.
     **/
    typedef typename Types<State<T> >::p_toT StateT;


    enum CallBackFunctionReturn {CONTINUE=0, STOP_IN_THIS_SUBSCRIPTION, STOP};
    enum SuscriptionMode {SUBSCRIPTION_OUT=0, SUBSCRIPTION_IN=1};

    State();
    State(int id);
    //State(const State& orig);
    virtual ~State();
    void setTransition(int transitionValue, State *stateToChange);
    string getName();
    int getId();
    void setName(string name);
    State *getStateFromTransitionValue(int transitionValue);
    void addSubscription(int subscriptionMode, int transitionValue,
             int (T::*pf)(int, int, int) );
    void addSubscription(int subscriptionMode,
             int (T::*pf)(int, int, int) );
    int runSubscribers(int subscriptionMode, int transitionValue
                                                    , int stateId);
    void setId(int id);
    void setOwner(T* owner);
    T* getOwner() const;

private:
    int id;
    string name;
    map<int, StateT> transitionMap;
    map<int, list<int (T::*)(int, int, int)> > transitionListeners[2];
    list<int (T::*)(int, int, int)> changeStateListener[2];
    T *owner;

};

#include "State.cpp"

#endif	/* STATE_H */

